home *** CD-ROM | disk | FTP | other *** search
/ Chip 1997 December / CHIPNET Aralık 1997.iso / linux / redhat / misc / src / install / fs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-11  |  31.8 KB  |  1,251 lines

  1. #include <alloca.h>
  2. #include <ctype.h>
  3. #include <errno.h>
  4. #include <fcntl.h>
  5. #include <linux/fs.h>
  6. #include <newt.h>
  7. #include <stdlib.h>
  8. #include <stdio.h>
  9. #include <string.h>
  10. #include <sys/mount.h>
  11. #include <sys/stat.h>
  12. #include <unistd.h>
  13.  
  14. #include "devices.h"
  15. #include "fs.h"
  16. #include "install.h"
  17. #include "log.h"
  18. #include "mkswap.h"
  19. #include "perror.h"
  20. #include "run.h"
  21. #include "smb.h"
  22. #include "windows.h"
  23.  
  24. int nfsmount(const char *spec, const char *node, int *flags,
  25.          char **extra_opts, char **mount_opts);
  26.  
  27. static int selectRootPartition(struct partitionTable table, int * rootPartNum);
  28. static int fstabCmp(const void * a, const void * b);
  29. static int mkdirChain(char * chain);
  30. static int mkdirIfNone(char * directory);
  31. static char * nstrdup(const char * foo);
  32. static void initFstabEntry(struct fstabEntry * e);
  33.  
  34. int canEnableSwap = 1;
  35. int badBlocks = 0;
  36.  
  37. struct nfsMountCallbackInfo {
  38.     newtComponent server, mntpoint, netpath;
  39.     char * serverVal, * netpathVal, * mntpointVal;
  40. } ;
  41.  
  42. static char * nstrdup(const char * foo) {
  43.     return foo ? strdup(foo) : NULL;
  44. }
  45.  
  46. static int fstabCmp(const void * a, const void * b) {
  47.     const struct fstabEntry * first = a;
  48.     const struct fstabEntry * second = b;
  49.  
  50.     if (first->type != second->type) {
  51.     if (first->type == PART_NFS)
  52.         return 1;
  53.     else if (second->type == PART_NFS)
  54.         return -1;
  55.     }
  56.  
  57.     return strcmp(first->mntpoint, second->mntpoint);
  58. }
  59.  
  60. static void initFstabEntry(struct fstabEntry * e) {
  61.     e->device = NULL;
  62.     e->netHost = NULL;
  63.     e->netPath = NULL;
  64.     e->mntpoint = NULL;
  65.     e->tagName = NULL;
  66.     e->size = 0;
  67.     e->type = PART_OTHER;
  68.     e->isMounted = 0;
  69.     e->doFormat = 0;
  70. }
  71.  
  72. newtComponent addPartitionListbox(struct partitionTable table,
  73.                      newtComponent form, int left, int top, 
  74.                      int height, int type, 
  75.                      int (*filter)(struct partition * part),
  76.                      int * numItems) {
  77.     newtComponent listbox, label;
  78.     int i;
  79.     char buf[80];
  80.  
  81.     listbox = newtListbox(left, top + 1, height, NEWT_LISTBOX_RETURNEXIT);
  82.  
  83.     label = newtLabel(left, top, "Device          Begin        End   "
  84.             "Size (k)");
  85.  
  86.     if (numItems) *numItems = 0;
  87.  
  88.     for (i = 0; i < table.count; i++) {
  89.     if (table.parts[i].type == type) {
  90.         if (!filter || filter(table.parts + i)) {
  91.         sprintf(buf, "/dev/%-5s  %9d  %9d  %9d", table.parts[i].device, 
  92.             table.parts[i].begin, table.parts[i].end, 
  93.             table.parts[i].size);
  94.         newtListboxAddEntry(listbox, buf, &table.parts[i]);
  95.  
  96.         if (numItems) (*numItems)++;
  97.         }
  98.     }
  99.     }
  100.  
  101.     newtFormAddComponents(form, label, listbox, NULL);
  102.  
  103.     return listbox;
  104. }
  105.  
  106. static int selectRootPartition(struct partitionTable table, int * rootPartNum) {
  107.     newtComponent okay, cancel, form, text, listbox, answer;
  108.     int i;
  109.     struct partition * rootPart = NULL;
  110.  
  111.     for (i = 0; i < table.count; i++) 
  112.     if (table.parts[i].type == PART_EXT2) break;
  113.  
  114.     if (i == table.count) {
  115.     newtOpenWindow(18, 6, 44, 11, "Select Root");
  116.     text = newtTextbox(1, 1, 42, 4, NEWT_TEXTBOX_WRAP);
  117.     newtTextboxSetText(text, "You don't have any Linux native partitions "
  118.                  "defined. You must return to repartition "
  119.                  "your hard drive.");
  120.     
  121.     okay = newtButton(17, 7, "Ok");
  122.  
  123.     form = newtForm(NULL, NULL, 0);
  124.     newtFormAddComponents(form, text, okay, NULL);
  125.     
  126.     newtRunForm(form);
  127.     newtFormDestroy(form);
  128.     newtPopWindow();
  129.  
  130.         return INST_CANCEL;
  131.     }
  132.  
  133.     *rootPartNum = i;
  134.  
  135.     newtOpenWindow(10, 2, 64, 19, "Select Root Partition");
  136.     text = newtTextbox(1, 1, 62, 4, NEWT_TEXTBOX_WRAP);
  137.     newtTextboxSetText(text, "The root partition forms the base of your Linux "
  138.                "filesystem. It must hold everything necessary for "
  139.                "booting and initializing your system. What partition "
  140.                "would you like to use for the root filesystem?");
  141.     okay = newtButton(15, 15, "Ok");
  142.     cancel = newtButton(38, 15, "Cancel");
  143.  
  144.     form = newtForm(NULL, NULL, 0);
  145.     listbox = addPartitionListbox(table, form, 7, 6, 7, PART_EXT2, NULL, NULL);
  146.  
  147.     newtFormAddComponents(form, text, okay, cancel, NULL);
  148.     answer = newtRunForm(form);
  149.             
  150.     if (answer != cancel) {
  151.     rootPart = newtListboxGetCurrent(listbox);
  152.     }
  153.  
  154.     newtFormDestroy(form);
  155.     newtPopWindow();
  156.  
  157.     *rootPartNum = (rootPart - table.parts);
  158.     if (!rootPart)
  159.     return INST_CANCEL;
  160.     else
  161.     return 0;
  162. }
  163.  
  164. static int badMountPoint(enum partitionTypes type, char * item) {
  165.     char * chptr = item;
  166.  
  167.     if (*chptr != '/') {
  168.     winMessage(33, 12, 30, 8, "Bad Mount Point",
  169.             "Mount points must begin with a leading /.");
  170.     return INST_ERROR;
  171.     } 
  172.  
  173.     if (*(chptr + 1) && *(chptr + strlen(chptr) - 1) == '/') {
  174.     winMessage(33, 12, 30, 8, "Bad Mount Point",
  175.             "Mount points may not end with a /.");
  176.     return INST_ERROR;
  177.     } 
  178.  
  179.     while (*chptr && isprint(*chptr)) chptr++;
  180.  
  181.     if (*chptr) {
  182.     winMessage(30, 10, 30, 10, "Bad Mount Point",
  183.             "Mount points may only printable characters.");
  184.     return INST_ERROR;
  185.     }
  186.  
  187.     if (type != PART_EXT2 && (
  188.      !strncmp(item, "/var", 4) ||
  189.      !strncmp(item, "/tmp", 4) ||
  190.      !strncmp(item, "/bin", 4) ||
  191.      !strncmp(item, "/sbin", 4) ||
  192.      !strncmp(item, "/etc", 4) ||
  193.      !strncmp(item, "/boot", 4) ||
  194.      !strncmp(item, "/dev", 4) ||
  195.      !strncmp(item, "/root", 4) ||
  196.      !strncmp(item, "/lib", 4))) {
  197.     winMessage(30, 10, 30, 10, "Bad Mount Point",
  198.             "System partitions must be on Linux Native "
  199.             "partitions.");
  200.     return INST_ERROR;
  201.     }
  202.  
  203.     if (type != PART_EXT2 && type != PART_NFS &&
  204.     !strncmp(item, "/usr", 4)) {
  205.     winMessage(25, 10, 30, 10, "Bad Mount Point",
  206.             "/usr must be on a Linux Native partition "
  207.             "or an NFS volume.");
  208.     return INST_ERROR;
  209.     }
  210.  
  211.     return 0;
  212. }
  213.  
  214. static char * restrdup(char * old, char * new) {
  215.     if (old) free(old);
  216.     if (new) return strdup(new); else return NULL;
  217. }
  218.  
  219. static void nfsMountCallback(newtComponent co, void * arg) {
  220.     struct nfsMountCallbackInfo * nfsinfo = arg;
  221.     char * chptr;
  222.     char * copy;
  223.  
  224.     if (!strlen(nfsinfo->netpathVal)) {
  225.     if (strchr(nfsinfo->serverVal, ':')) {
  226.         chptr = copy = alloca(strlen(nfsinfo->serverVal) + 1);
  227.         strcpy(copy, nfsinfo->serverVal);
  228.         chptr = strchr(copy, ':');
  229.         *chptr = '\0';
  230.         chptr++;
  231.         newtEntrySet(nfsinfo->server, copy, 1);
  232.         newtEntrySet(nfsinfo->netpath, chptr, 1);
  233.     }
  234.     }
  235.  
  236.     if (strlen(nfsinfo->netpathVal) && !strlen(nfsinfo->mntpointVal)) {
  237.     newtEntrySet(nfsinfo->mntpoint, nfsinfo->netpathVal, 1);
  238.     }
  239. }
  240.  
  241. static int editNetMountPoint(struct fstabEntry * item) {
  242.     newtComponent form, server, path, point, okay, cancel, answer;
  243.     char * pointValue, * pathValue, * serverValue;
  244.     int done = 0;
  245.     struct nfsMountCallbackInfo nfsinfo;
  246.  
  247.     newtOpenWindow(10, 7, 50, 10, "Edit Network Mount Point");
  248.  
  249.     form = newtForm(NULL, NULL, 0);
  250.  
  251.     newtFormAddComponent(form, newtLabel(1, 1, "NFS Server  :"));
  252.     newtFormAddComponent(form, newtLabel(1, 2, "NFS Path    :"));
  253.     newtFormAddComponent(form, newtLabel(1, 3, "Mount point :"));
  254.  
  255.     server = newtEntry(17, 1, item->mntpoint, 20, &serverValue, 
  256.               NEWT_ENTRY_SCROLL | NEWT_ENTRY_RETURNEXIT);
  257.     path = newtEntry(17, 2, item->mntpoint, 20, &pathValue, 
  258.               NEWT_ENTRY_SCROLL | NEWT_ENTRY_RETURNEXIT);
  259.     point = newtEntry(17, 3, item->mntpoint, 20, &pointValue, 
  260.               NEWT_ENTRY_SCROLL | NEWT_ENTRY_RETURNEXIT);
  261.  
  262.     nfsinfo.server = server;
  263.     nfsinfo.mntpoint = point;
  264.     nfsinfo.netpath = path;
  265.  
  266.     nfsinfo.serverVal = serverValue;
  267.     nfsinfo.netpathVal = pathValue;
  268.     nfsinfo.mntpointVal = pointValue;
  269.  
  270.     newtComponentAddCallback(server, nfsMountCallback, &nfsinfo);
  271.     newtComponentAddCallback(path, nfsMountCallback, &nfsinfo);
  272.  
  273.     okay = newtButton(10, 6, "Ok");
  274.     cancel = newtButton(30, 6, "Cancel");
  275.  
  276.     newtFormAddComponents(form, server, path, point, okay, cancel, NULL);
  277.  
  278.     do {
  279.     answer = newtRunForm(form);
  280.  
  281.     if (answer == cancel) {
  282.         done = 1;
  283.     } else if (*pointValue) {
  284.         if (!badMountPoint(item->type, pointValue)) 
  285.         done = 1;
  286.     }
  287.     } while (!done);
  288.  
  289.     if (answer != cancel) {
  290.     item->mntpoint = restrdup(item->mntpoint, pointValue);
  291.     item->netPath = restrdup(item->netPath, pathValue);
  292.     item->netHost = restrdup(item->netHost, serverValue);
  293.  
  294.     if (item->device) free(item->device);
  295.     item->device = malloc(strlen(pathValue) + strlen(serverValue) + 5);
  296.     sprintf(item->device, "%s:%s", serverValue, pathValue);
  297.     }
  298.  
  299.     newtPopWindow();
  300.  
  301.     if (answer == cancel)
  302.     return INST_CANCEL;
  303.     return 0;
  304. }        
  305.  
  306. static void editDeviceMountPoint(struct fstabEntry * item) {
  307.     newtComponent form, entry, okay, cancel, clear, answer;
  308.     char buf[50];
  309.     char * entryValue;
  310.     int done = 0;
  311.  
  312.     newtOpenWindow(10, 7, 50, 10, "Edit Mount Point");
  313.  
  314.     form = newtForm(NULL, NULL, 0);
  315.  
  316.     strcpy(buf,"Device      : /dev/");
  317.     strcat(buf, item->device);
  318.     newtFormAddComponent(form, newtLabel(1, 1, buf));
  319.     newtFormAddComponent(form, newtLabel(1, 3, "Mount point :"));
  320.  
  321.     entry = newtEntry(17, 3, item->mntpoint, 20, &entryValue, 
  322.               NEWT_ENTRY_SCROLL | NEWT_ENTRY_RETURNEXIT);
  323.  
  324.     okay = newtButton(5, 6, "Ok");
  325.     clear = newtButton(20, 6, "Clear");
  326.     cancel = newtButton(35, 6, "Cancel");
  327.  
  328.     newtFormAddComponents(form, entry, okay, clear, cancel, NULL);
  329.  
  330.     do {
  331.     newtFormSetCurrent(form, entry);
  332.     answer = newtRunForm(form);
  333.  
  334.     if (answer == clear)
  335.         newtEntrySet(entry, "", 1);
  336.     else if (answer == cancel || !*entryValue) {
  337.         done = 1;
  338.     } else if (*entryValue) {
  339.         if (!badMountPoint(item->type, entryValue)) 
  340.         done = 1;
  341.     }
  342.     } while (!done);
  343.  
  344.     if (answer != cancel) {
  345.     item->mntpoint = restrdup(item->mntpoint, entryValue);
  346.     }
  347.  
  348.     newtPopWindow();
  349. }        
  350.  
  351. void freeFstab(struct fstab fstab) {
  352.     int i;
  353.  
  354.     for (i = 0; i < fstab.numEntries; i++) {
  355.     if (fstab.entries[i].mntpoint) free(fstab.entries[i].mntpoint);
  356.     if (fstab.entries[i].device) free(fstab.entries[i].device);
  357.     if (fstab.entries[i].netPath) free(fstab.entries[i].netPath);
  358.     if (fstab.entries[i].netHost) free(fstab.entries[i].netHost);
  359.     }
  360.  
  361.     if (fstab.numEntries) free(fstab.entries);
  362. }
  363.  
  364. struct fstab copyFstab(struct fstab * fstab) {
  365.     struct fstab newfstab;
  366.     int i, j;
  367.  
  368.     if (!fstab->numEntries) {
  369.     newfstab.numEntries = 0;
  370.     newfstab.entries = malloc(1);
  371.     return newfstab;
  372.     }
  373.  
  374.     /* duplicate the current fstab */
  375.     newfstab.numEntries = fstab->numEntries;
  376.     newfstab.entries = malloc(fstab->numEntries * sizeof(struct fstabEntry));
  377.     for (i = j = 0; i < newfstab.numEntries; i++) {
  378.     if (fstab->entries[i].mntpoint) {
  379.         newfstab.entries[j] = fstab->entries[i];
  380.         newfstab.entries[j].mntpoint = nstrdup(fstab->entries[i].mntpoint);
  381.         newfstab.entries[j].device = nstrdup(fstab->entries[i].device);
  382.         newfstab.entries[j].netPath = nstrdup(fstab->entries[i].netPath);
  383.         newfstab.entries[j].netHost = nstrdup(fstab->entries[i].netHost);
  384.         j++;
  385.     }
  386.     }
  387.  
  388.     newfstab.numEntries = j;
  389.  
  390.     /* return the memory we don't actually need */
  391.     newfstab.entries = realloc(newfstab.entries, j * sizeof(struct fstabEntry));
  392.  
  393.     return newfstab;
  394. }
  395.  
  396. int setupMountTable(struct partitionTable table, struct fstab * finalFstab,
  397.             struct netInterface * intf, struct netConfig * netc,
  398.             struct driversLoaded ** dl) {
  399.     int rootPartNum = -1;
  400.     int rc, hasdups;
  401.     newtComponent f, okay, text, listbox, label, cancel, edit, answer;
  402.     newtComponent addnfs;
  403.     char buf[80];
  404.     int i, j, numMountable, numLinux;
  405.     int partNum;
  406.     struct fstab fstab;
  407.     int fstabNum;
  408.     struct fstabEntry entry, * curr;
  409.     int * fstabEntNum, * numptr;
  410.     static int firstTime = 1;
  411.     const char * basicFormat = "%-10s  %14s  %-20s %-18s";
  412.     const char * devFormat = "/dev/%-5s  %14d  %-20s %-18s";
  413.     const char * nfsFormat = "%-27s %-20s %-18s";
  414.  
  415.     fstab = copyFstab(finalFstab);
  416.  
  417.     if (firstTime) {
  418.     /* First, make them pick a root partition */
  419.     if ((rc = selectRootPartition(table, &rootPartNum))) {
  420.         freeFstab(fstab);
  421.         return rc;
  422.     }
  423.     firstTime = 0;
  424.  
  425.     for (i = partNum = 0; i < table.count; i++) {
  426.         if (i == rootPartNum) {
  427.         initFstabEntry(&entry);
  428.         entry.device = strdup(table.parts[i].device);
  429.         entry.size = table.parts[i].size;
  430.         entry.type = table.parts[i].type;
  431.         entry.tagName = table.parts[i].tagName;
  432.         entry.mntpoint = strdup("/");
  433.         addFstabEntry(&fstab, entry);
  434.         break;
  435.         }
  436.     }
  437.  
  438.     freeFstab(*finalFstab);
  439.     *finalFstab = copyFstab(&fstab);
  440.     }    
  441.  
  442.     /* If only one mountable partition exists, it would have been set up
  443.        as root above so we can stop here */
  444.     numLinux = numMountable = 0;
  445.     for (i = partNum = 0; i < table.count; i++) {
  446.     if (table.parts[i].type == PART_EXT2)
  447.         numMountable++, numLinux++;
  448.     else if (table.parts[i].type == PART_DOS ||
  449.              table.parts[i].type == PART_HPFS)
  450.         numMountable++;
  451.     }
  452.     if (!numMountable) {
  453.     errorWindow("You don't have any mountable partitions!");
  454.     return INST_ERROR;
  455.     } else if (!numLinux) {
  456.     errorWindow("You don't have any Linux partitions available!");
  457.     return INST_ERROR;
  458.     } else if (numMountable == 1)
  459.     return 0;
  460.  
  461.     newtOpenWindow(2, 2, 75, 19, "Partition Disk");
  462.  
  463.     f = newtForm(NULL, NULL, 0);
  464.     text = newtTextbox(1, 1, 72, 4, NEWT_TEXTBOX_WRAP);
  465.     newtTextboxSetText(text, "You may now mount other partitions within "
  466.                "your filesystem. Many users like to use separate "
  467.                "partitions for /usr and /home for example. You may "
  468.                "also mount your DOS or OS/2 partitions to make them "
  469.                "visible to Linux.");
  470.  
  471.     okay = newtButton(6, 15, "Ok");
  472.     addnfs = newtButton(20, 15, "Add NFS");
  473.     edit = newtButton(38, 15, "Edit");
  474.     cancel = newtButton(54, 15, "Cancel");
  475.  
  476.     sprintf(buf, basicFormat, "Device", "Size", "Partition type", 
  477.         "Mount point");
  478.     label = newtLabel(1, 5, buf);
  479.  
  480.     listbox = newtListbox(1, 6, 8, NEWT_LISTBOX_RETURNEXIT);
  481.  
  482.     fstabEntNum = malloc(table.count * sizeof(*fstabEntNum));
  483.  
  484.     for (i = partNum = 0; i < table.count; i++) {
  485.     if (table.parts[i].type == PART_EXT2 || 
  486.         table.parts[i].type == PART_DOS ||
  487.         table.parts[i].type == PART_HPFS) {
  488.  
  489.         for (j = 0; j < fstab.numEntries; j++) 
  490.         if (!strcmp(table.parts[i].device, fstab.entries[j].device))
  491.             break;
  492.  
  493.         if (j < fstab.numEntries) {
  494.         fstabNum = j;
  495.         } else {
  496.         initFstabEntry(&entry);
  497.         entry.device = strdup(table.parts[i].device);
  498.         entry.size = table.parts[i].size;
  499.         entry.type = table.parts[i].type;
  500.         entry.tagName = table.parts[i].tagName;
  501.         fstabNum = addFstabEntry(&fstab, entry);
  502.         }
  503.  
  504.         sprintf(buf, devFormat, table.parts[i].device, 
  505.             table.parts[i].size, table.parts[i].tagName, 
  506.             fstab.entries[fstabNum].mntpoint ? 
  507.             fstab.entries[fstabNum].mntpoint : "");
  508.         fstabEntNum[partNum] = fstabNum;
  509.         newtListboxAddEntry(listbox, buf, fstabEntNum + partNum);
  510.         partNum++;
  511.     } 
  512.     }
  513.  
  514.     newtFormAddComponents(f, text, label, listbox, okay, addnfs, edit, cancel, 
  515.                 NULL);
  516.  
  517.     do { 
  518.     answer = newtRunForm(f);
  519.     if (answer == listbox || answer == edit) {
  520.         numptr = newtListboxGetCurrent(listbox);
  521.         curr = fstab.entries + *numptr;
  522.  
  523.         if (curr->type == PART_NFS) {
  524.         editNetMountPoint(curr);
  525.         sprintf(buf, nfsFormat, curr->device, curr->tagName,
  526.             curr->mntpoint);
  527.         } else {
  528.         editDeviceMountPoint(curr);
  529.         sprintf(buf, devFormat, curr->device, curr->size, 
  530.             curr->tagName, curr->mntpoint ? curr->mntpoint : "");
  531.         }
  532.  
  533.         newtListboxSetEntry(listbox, numptr - fstabEntNum, buf);
  534.     } else if (answer == addnfs) {
  535.         initFstabEntry(&entry);
  536.         entry.type = PART_NFS;
  537.         entry.tagName = "NFS Mount";
  538.         entry.device = NULL;
  539.         entry.mntpoint = NULL;
  540.  
  541.         if (!intf->isConfigured) {
  542.         rc = bringUpNetworking(intf, netc, dl);
  543.         } else {
  544.         rc = 0;
  545.         }
  546.  
  547.         if (!rc && !editNetMountPoint(&entry)) {
  548.         fstabNum = addFstabEntry(&fstab, entry);
  549.         fstabEntNum = realloc(fstabEntNum, 
  550.                       sizeof(*fstabEntNum) * fstabNum);
  551.  
  552.         sprintf(buf, nfsFormat, entry.device, entry.tagName,
  553.             entry.mntpoint);
  554.  
  555.         newtListboxAddEntry(listbox, buf, fstabEntNum + fstabNum);
  556.         /*newtListboxSetCurrent(listbox, fstabNum);*/
  557.         }
  558.     } else if (answer != cancel) {
  559.         answer = okay;
  560.         for (i = 0; i < fstab.numEntries; i++) 
  561.         if (fstab.entries[i].mntpoint &&
  562.             !strcmp(fstab.entries[i].mntpoint, "/")) break;
  563.  
  564.         if (i == fstab.numEntries) {
  565.         winMessage(30, 7, 30, 10, "No Root Partition",
  566.                 "You must assign a root (/) partition for the "
  567.                 "install to proceed.");
  568.         answer = NULL;
  569.         continue;
  570.         }
  571.  
  572.         hasdups = 0;
  573.         for (i = 0; i < fstab.numEntries; i++) 
  574.         for (j = i + 1; j < fstab.numEntries; j++) 
  575.             if (fstab.entries[i].type != PART_SWAP &&
  576.             fstab.entries[i].mntpoint &&
  577.                 fstab.entries[j].mntpoint &&
  578.             !strcmp(fstab.entries[i].mntpoint,
  579.                         fstab.entries[j].mntpoint))
  580.             hasdups = 1;
  581.  
  582.         if (hasdups) {
  583.         winMessage(30, 7, 30, 10, "Duplicate Mounts",
  584.                 "You may not use the same mount point multiple "
  585.                 "times.");
  586.         answer = NULL;
  587.         }
  588.     }
  589.     } while (answer != okay && answer != cancel);
  590.  
  591.     newtFormDestroy(f);
  592.     newtPopWindow();
  593.  
  594.     free(fstabEntNum);
  595.  
  596.     if (answer == cancel) { 
  597.     freeFstab(fstab);
  598.     return INST_CANCEL;
  599.     }
  600.  
  601.     freeFstab(*finalFstab);
  602.     *finalFstab = copyFstab(&fstab);
  603.     freeFstab(fstab);
  604.  
  605.     /* Sort by mount point. This makes mounting everything in the proper
  606.        order trivial */
  607.  
  608.     qsort(finalFstab->entries, finalFstab->numEntries, 
  609.       sizeof(*finalFstab->entries), fstabCmp);
  610.  
  611.     return 0;
  612. }
  613.  
  614. static int mkExt2Filesystem(char * dev) {
  615.     char * mke2fsargs[] = { "mke2fs", NULL, NULL, NULL};
  616.     int rc;
  617.     char message[80];
  618.  
  619.     mke2fsargs[1] = alloca(strlen(dev) + 6);
  620.     strcpy(mke2fsargs[1], "/tmp/");
  621.     strcat(mke2fsargs[1], dev);
  622.  
  623.     if (badBlocks)
  624.     mke2fsargs[2] = "-c";
  625.  
  626.     sprintf(message, "Making ext2 filesystem on /dev/%s...", dev);
  627.     winStatus(45, 3, "Running", message);
  628.  
  629.     devMakeInode(dev, mke2fsargs[1]);
  630.     rc = runProgram(RUN_LOG, "/usr/bin/mke2fs", mke2fsargs);
  631.     devRemoveInode(mke2fsargs[1]);
  632.  
  633.     newtPopWindow();
  634.  
  635.     if (rc)
  636.     return INST_ERROR;
  637.     else
  638.     return 0;
  639. }
  640.  
  641. int queryFormatFilesystems(struct fstab * fstab) {
  642.     newtComponent form, checkList, okay, cancel, sb, text, answer;
  643.     newtComponent checkbox;
  644.     char * states;
  645.     char doCheck = ' ';
  646.     newtComponent * checks;
  647.     char buf[80];
  648.     int i, top;
  649.  
  650.     newtOpenWindow(11, 2, 57, 19, "Format Partitions");
  651.  
  652.     form = newtForm(NULL, NULL, 0);
  653.  
  654.     if (fstab->numEntries > 4) 
  655.     sb = newtVerticalScrollbar(47, 7, 4, 9, 10);
  656.     else
  657.     sb = NULL;
  658.  
  659.     checkList = newtForm(sb, NULL, 0);
  660.     newtFormSetHeight(checkList, 4);
  661.  
  662.     if (sb)
  663.     newtFormAddComponent(checkList, sb);
  664.  
  665.     text = newtTextbox(1, 1, 55, 6, NEWT_TEXTBOX_WRAP);
  666.     newtTextboxSetText(text, "What partitions would you like to "
  667.                "format? We strongly suggest formatting all of the "
  668.                "system partitions, including /, /usr, and /var. There "
  669.                "is no need to format /home or /usr/local if they "
  670.                "have already been configured during a previous "
  671.                "install.");
  672.  
  673.     checks = alloca(sizeof(newtComponent) * fstab->numEntries);
  674.     states = alloca(sizeof(char) * fstab->numEntries);
  675.     for (i = 0, top = 0; i < fstab->numEntries; i++) {
  676.     if (fstab->entries[i].doFormat)
  677.         states[i] = '*';
  678.     else
  679.         states[i] = ' ';
  680.  
  681.     if (fstab->entries[i].type == PART_EXT2) {
  682.         sprintf(buf, "/dev/%-5s  %-33s", fstab->entries[i].device, 
  683.            fstab->entries[i].mntpoint);
  684.         checks[i] = newtCheckbox(3, 7 + top++, buf, states[i], NULL, 
  685.                      &states[i]);
  686.         newtFormAddComponent(checkList, checks[i]);
  687.     } else {
  688.         checks[i] = NULL;
  689.     }
  690.     }
  691.  
  692.     okay = newtButton(12, 14, "Ok");
  693.     cancel = newtButton(34, 14, "Cancel");
  694.     checkbox = newtCheckbox(10, 12, "Check for bad blocks during format",
  695.                 badBlocks ? '*' : ' ', NULL, &doCheck);
  696.     
  697.     newtFormAddComponents(form, text, checkList, checkbox, okay, cancel, NULL);
  698.  
  699.     answer = newtRunForm(form);
  700.  
  701.     newtFormDestroy(form);
  702.     newtPopWindow();
  703.  
  704.     if (answer == cancel) return INST_CANCEL;
  705.  
  706.     for (i = 0; i < fstab->numEntries; i++) {
  707.         if (states[i] != ' ') 
  708.         fstab->entries[i].doFormat = 1; 
  709.     }
  710.  
  711.     if (doCheck == ' ')
  712.     badBlocks = 0;
  713.     else
  714.     badBlocks = 1;
  715.  
  716.     return 0;
  717. }
  718.  
  719. int formatFilesystems(struct fstab * fstab) {
  720.     int i;
  721.  
  722.     for (i = 0; i < fstab->numEntries; i++) {
  723.         if (fstab->entries[i].doFormat)
  724.         mkExt2Filesystem(fstab->entries[i].device);
  725.     }
  726.  
  727.     return 0;
  728. }
  729.  
  730. int doMount(char * dev, char * where, char * fs, int rdonly, int istty) {
  731.     return doPwMount(dev, where, fs, rdonly, istty, NULL, NULL);
  732. }
  733.  
  734. int doPwMount(char * dev, char * where, char * fs, int rdonly, int istty,
  735.         char * acct, char * pw) { 
  736.     char * buf = NULL;
  737.     int isnfs = 0;
  738.     char * mount_opt = NULL;
  739.     long int flag;
  740.     char * chptr;
  741.  
  742.     if (!strcmp(fs, "nfs")) isnfs = 1;
  743.  
  744.     logMessage("mounting %s on %s as type %s", dev, where, fs);
  745.  
  746.     if (testing) {
  747.     messageWindow("Test mount", "I would mount /dev/%s on %s",
  748.         "using a(n) %s filesystem.", dev, where, fs);
  749.     } else if (!strcmp(fs, "smb")) {
  750.     mkdirChain(where);
  751.  
  752.     if (!acct) acct = "guest";
  753.     if (!pw) pw = "";
  754.  
  755.     buf = alloca(strlen(dev) + 1);
  756.     strcpy(buf, dev);
  757.     chptr = buf;
  758.     while (*chptr && *chptr != ':') chptr++;
  759.     if (!*chptr) {
  760.         logMessage("bad smb mount point %s", where);
  761.         return 0;
  762.     } 
  763.     
  764.     *chptr = '\0';
  765.     chptr++;
  766.  
  767. #ifdef __i386__
  768.     logMessage("mounting smb filesystem from %s path %s on %s",
  769.             buf, chptr, where);
  770.     return smbmount(buf, chptr, acct, pw, "localhost", where);
  771. #else 
  772.     errorWindow("smbfs only works on Intel machines");
  773. #endif
  774.     } else {
  775.     mkdirChain(where);
  776.  
  777.       if (!isnfs && *dev == '/') {
  778.         buf = dev;
  779.     } else if (!isnfs) {
  780.         buf = alloca(200);
  781.         strcpy(buf, "/tmp/");
  782.         strcat(buf, dev);
  783.  
  784.         if (devMakeInode(dev, buf)) return 1;
  785.     } else {
  786.         char * junk = NULL;
  787.         int morejunk = 0;
  788.  
  789.         buf = dev;
  790.         logMessage("calling nfsmount(%s, %s, &morejunk, &junk, &mount_opt)",
  791.             buf, where);
  792.  
  793.         if (nfsmount(buf, where, &morejunk, &junk, &mount_opt))
  794.         logMessage("\tnfsmount returned non-zero");
  795.     }
  796.  
  797.     flag = MS_MGC_VAL;
  798.     if (rdonly)
  799.         flag |= MS_RDONLY;
  800.     
  801.     logMessage("calling mount(%s, %s, %s, %ld, %p)", buf, where, fs, 
  802.             flag, mount_opt);
  803.  
  804.     if (mount(buf, where, fs, flag, mount_opt)) {
  805.         if (istty) {
  806.         fprintf(stderr, "mount failed: %s\n", strerror(errno));
  807.         } else {
  808.         messageWindow("Error", perrorstr("mount failed"));
  809.         }
  810.         return 1;
  811.     }
  812.  
  813.     if (!isnfs) devRemoveInode(buf);
  814.     }
  815.  
  816.     return 0;
  817. }
  818.  
  819. int mountFilesystems(struct fstab * fstab) {
  820.     int i;
  821.     char buf[1000];
  822.  
  823.     /* don't bother mounting odd (non-ext2) filesystems - we don't need
  824.        them for installs */
  825.  
  826.     /* what about NFS? we should probably mount them to check mount integrity,
  827.        but we don't know if networking is working well enough for us to do
  828.        this */
  829.    
  830.     chdir("/");
  831.  
  832.     for (i = 0; i < fstab->numEntries; i++) {
  833.     strcpy(buf, "/mnt");
  834.     strcat(buf, fstab->entries[i].mntpoint);
  835.  
  836.     if (fstab->entries[i].type == PART_EXT2 ||
  837.         fstab->entries[i].type == PART_NFS ) {
  838.         if (fstab->entries[i].type == PART_EXT2 &&
  839.         !doMount(fstab->entries[i].device, buf, "ext2", 0, 0))
  840.         fstab->entries[i].isMounted = 1;
  841.         else if (fstab->entries[i].type == PART_NFS &&
  842.         !doMount(fstab->entries[i].device, buf, "nfs", 0, 0))
  843.         fstab->entries[i].isMounted = 1;
  844.         else {
  845.         logMessage("unmounting all filesystems due to mount error");
  846.         umountFilesystems(fstab);
  847.         return INST_ERROR;
  848.         }
  849.     } else {
  850.         logMessage("creating directory %s", buf);
  851.         mkdirChain(buf);
  852.     }
  853.     }
  854.  
  855.     return 0;
  856. }
  857.  
  858. int umountFilesystems(struct fstab * fstab) {
  859.     char buf[1000];
  860.     int i;
  861.     int olderrno;
  862.  
  863.     logMessage("unmounting all filesystems");
  864.  
  865.     chdir("/");
  866.  
  867.     if (testing) return 0;
  868.  
  869.     for (i = fstab->numEntries - 1; i >= 0; i--) {
  870.     if (fstab->entries[i].isMounted) {
  871.         strcpy(buf, "/mnt");
  872.         strcat(buf, fstab->entries[i].mntpoint);
  873.  
  874.         fstab->entries[i].isMounted = 0;
  875.         if (umount(buf)) {
  876.         olderrno = errno;
  877.         logMessage("error unmounting %s: %s\n", buf, strerror(errno));
  878.         errno = olderrno;
  879.         errorWindow("error unmounting filesystem: %s");
  880.         }
  881.     }    
  882.     }
  883.  
  884.     return 0;
  885. }
  886.  
  887. static int mkdirChain(char * origChain) {
  888.     char * chain;
  889.     char * chptr;
  890.  
  891.     chain = alloca(strlen(origChain) + 1);
  892.     strcpy(chain, origChain);
  893.     chptr = chain;
  894.  
  895.     if (testing) return 0;
  896.  
  897.     while ((chptr = strchr(chptr, '/'))) {
  898.     *chptr = '\0';
  899.     if (mkdirIfNone(chain)) {
  900.         *chptr = '/';
  901.         return INST_ERROR;
  902.     }
  903.  
  904.     *chptr = '/';
  905.     chptr++;
  906.     }
  907.  
  908.     if (mkdirIfNone(chain))
  909.     return INST_ERROR;
  910.  
  911.     return 0;
  912. }
  913.  
  914. static int mkdirIfNone(char * directory) {
  915.     int rc, mkerr;
  916.     char * chptr;
  917.  
  918.     /* If the file exists it *better* be a directory -- I'm not going to
  919.        actually check or anything */
  920.     if (!access(directory, X_OK)) return 0;
  921.  
  922.     /* if the path is '/' we get ENOFILE not found" from mkdir, rather
  923.        then EEXIST which is weird */
  924.     for (chptr = directory; *chptr; chptr++)
  925.         if (*chptr != '/') break;
  926.     if (!*chptr) return 0;
  927.  
  928.     rc = mkdir(directory, 0755);
  929.     mkerr = errno;
  930.  
  931.     logMessage("creating directory %s rc = %d", directory, rc);
  932.  
  933.     if (!rc || mkerr == EEXIST) return 0;
  934.  
  935.     logMessage("    error: %s", strerror(mkerr));
  936.  
  937.     return INST_ERROR;
  938. }
  939.  
  940. int writeFstab(struct fstab * fstab) {
  941.     int i;
  942.     FILE * f;
  943.     int fd;
  944.     char * fs = NULL;
  945.     int freq = 0;
  946.     int passno = 0;
  947.     int bad;
  948.     char buf[4096];
  949.     char * chptr, * cddev = NULL;
  950.     char * devFormat = "/dev/%-18s %-23s %-7s %-15s %d %d\n";
  951.     char * nfsFormat = "%-23s %-23s %-7s %-15s %d %d\n";
  952.     char * procFormat = "%-23s %-23s %-7s %-15s %d %d\n";
  953.     char * options;
  954.     char * format;
  955.  
  956.     logMessage("scanning /proc/mounts for iso9660 filesystems");
  957.     fd = open("/proc/mounts", O_RDONLY);
  958.     if (fd < 0) {
  959.     logMessage("\terror opening /proc/mounts -- skipping check: %s",
  960.             strerror(errno));
  961.     } else {
  962.     i = read(fd, buf, sizeof(buf) - 1);
  963.     if (i < 0) {
  964.         logMessage("\terror reading /proc/mounts -- skipping check: %s",
  965.                 strerror(errno));
  966.     } else {
  967.         buf[i] = 0;
  968.         if ((chptr = strstr(buf, "iso9660"))) {
  969.         chptr--;
  970.  
  971.         /* skip the mount point */
  972.         while (*chptr == ' ') chptr--;
  973.         while (*chptr != ' ') chptr--;
  974.         while (*chptr == ' ') chptr--;
  975.  
  976.         chptr++;
  977.         *chptr = '\0';
  978.         while (*chptr != '/') chptr--;
  979.         cddev = strdup(chptr + 1);
  980.         
  981.         logMessage("found mounted cdrom drive %s", cddev);
  982.         }
  983.     }
  984.     }
  985.  
  986.     #ifndef __sparc__
  987.     if (!cddev) {
  988.     if (findAtapi(&cddev)) cddev = NULL;
  989.     }
  990.     #endif
  991.     if (!cddev) {
  992.     if (findSCSIcdrom(&cddev)) cddev = NULL;
  993.     }
  994.  
  995.     if (testing) {
  996.     if (cddev) free(cddev);
  997.     return 0;
  998.     }
  999.  
  1000.     logMessage("creating /etc/fstab");
  1001.  
  1002.     f = fopen("/mnt/etc/fstab", "w");
  1003.     if (!f) {
  1004.     if (cddev) free(cddev);
  1005.     errorWindow("error creating /mnt/etc/fstab");
  1006.     return INST_ERROR;
  1007.     }
  1008.  
  1009.     for (i = 0; i < fstab->numEntries; i++) {
  1010.     if (!fstab->entries[i].mntpoint) continue;
  1011.  
  1012.     passno = 0;
  1013.     freq = 0;
  1014.     format = devFormat;
  1015.         options = "defaults";
  1016.  
  1017.     bad = 0;
  1018.     switch (fstab->entries[i].type) {
  1019.       case PART_EXT2:
  1020.         freq = 1;
  1021.         fs = "ext2";
  1022.         if (!strcmp(fstab->entries[i].mntpoint, "/"))
  1023.         passno = 1;
  1024.         else
  1025.         passno = 2;
  1026.       
  1027.         break;
  1028.  
  1029.       case PART_NFS:
  1030.         fs = "nfs";
  1031.         options = "ro";
  1032.         format = nfsFormat;
  1033.         break;
  1034.  
  1035.       case PART_SWAP:
  1036.         fs = "swap";
  1037.         break;
  1038.  
  1039.       case PART_DOS:
  1040.         fs = "msdos";
  1041.         break;
  1042.  
  1043.       case PART_HPFS:
  1044.         fs = "hpfs";
  1045.         break;
  1046.  
  1047.       default:
  1048.         bad = 1;
  1049.     }
  1050.  
  1051.     if (!bad)
  1052.         fprintf(f, format, fstab->entries[i].device, 
  1053.             fstab->entries[i].mntpoint, fs, options, freq, passno);
  1054.     }
  1055.  
  1056.     fprintf(f, devFormat, "fd0", "/mnt/floppy", "ext2", "noauto", 0, 0);
  1057.     if (cddev) {
  1058.     if (mkdir("/mnt/mnt/cdrom", 0755)) 
  1059.         logMessage("failed to mkdir /mnt/mnt/cdrom: %s", strerror(errno));
  1060.  
  1061.     if (symlink(cddev, "/mnt/dev/cdrom"))
  1062.         logMessage("failed to symlink /mnt/dev/cdrom: %s", strerror(errno));
  1063.  
  1064.     fprintf(f, devFormat, "cdrom", "/mnt/cdrom", "iso9660", "noauto,ro", 
  1065.         0, 0);
  1066.     free(cddev);
  1067.     }
  1068.  
  1069.     fprintf(f, procFormat, "none", "/proc", "proc", "defaults", 0, 0);
  1070.  
  1071.     fclose(f);
  1072.  
  1073.  
  1074.     return 0;
  1075. }
  1076.  
  1077. int addFstabEntry(struct fstab * fstab, struct fstabEntry entry) {
  1078.     int i;
  1079.  
  1080.     for (i = 0; i < fstab->numEntries; i++) 
  1081.     if (!strcmp(entry.device, fstab->entries[i].device))
  1082.         break;
  1083.  
  1084.     if (i == fstab->numEntries) {
  1085.     fstab->numEntries++;
  1086.     if (fstab->numEntries > 1)
  1087.         fstab->entries = realloc(fstab->entries, 
  1088.                 sizeof(entry) * fstab->numEntries);
  1089.     else
  1090.         fstab->entries = malloc(sizeof(entry));
  1091.     }
  1092.  
  1093.     fstab->entries[i] = entry;
  1094.  
  1095.     return i;
  1096. }
  1097.  
  1098. int activeSwapSpace(struct partitionTable * table, struct fstab * finalFstab) {
  1099.     newtComponent form, checkList, okay, cancel, sb, text, answer, label;
  1100.     newtComponent check, partition, cont, checkbox;
  1101.     char * states;
  1102.     char buf[80];
  1103.     int i, top, j;
  1104.     struct fstabEntry entry;
  1105.     struct fstabEntry ** entries;
  1106.     struct fstab fstab;
  1107.     static int firstTime = 1;
  1108.     static int chkBadBlocks = 1;
  1109.     char doCheck = ' ';
  1110.  
  1111.     fstab = copyFstab(finalFstab);    
  1112.  
  1113.     form = newtForm(NULL, NULL, 0);
  1114.  
  1115.     for (i = j = 0; i < table->count; i++)
  1116.     if (table->parts[i].type == PART_SWAP)
  1117.         j++;
  1118.  
  1119.     if (!j) {
  1120.     newtOpenWindow(18, 6, 44, 10, "Setup Swap");
  1121.     text = newtTextbox(1, 1, 42, 3, NEWT_TEXTBOX_WRAP);
  1122.     newtTextboxSetText(text, "You don't have any swap space defined. Would "
  1123.                  "you like to continue, or repartition your disk?");
  1124.     
  1125.     cont = newtButton(6, 6, "Continue");
  1126.     partition = newtButton(25, 6, "Cancel");
  1127.  
  1128.     form = newtForm(NULL, NULL, 0);
  1129.     newtFormAddComponents(form, text, cont, partition, NULL);
  1130.     
  1131.     answer = newtRunForm(form);
  1132.     newtFormDestroy(form);
  1133.     newtPopWindow();
  1134.  
  1135.     if (answer == partition)
  1136.        return INST_CANCEL;
  1137.     
  1138.     return 0;
  1139.     }
  1140.  
  1141.     newtOpenWindow(15, 4, 54, 15, "Active Swap Space");
  1142.     
  1143.     if (j > 3)
  1144.     sb = newtVerticalScrollbar(47, 7, 3, 9, 10);
  1145.     else
  1146.     sb = NULL;
  1147.  
  1148.     checkList = newtForm(sb, NULL, 0);
  1149.     newtFormSetHeight(checkList, 3);
  1150.  
  1151.     if (sb)
  1152.     newtFormAddComponent(checkList, sb);
  1153.  
  1154.     text = newtTextbox(1, 1, 52, 4, NEWT_TEXTBOX_WRAP);
  1155.     newtTextboxSetText(text, "What partitions would you like to "
  1156.                "use for swap space? This will destroy any "
  1157.                "information already on the partition.");
  1158.  
  1159.     label = newtLabel(4, 5, "  Device          Begin        End   Size (k)");
  1160.  
  1161.     states = alloca(sizeof(char) * table->count);
  1162.     entries = alloca(sizeof(*entries) * table->count);
  1163.  
  1164.     for (i = 0, top = 0; i < table->count; i++) {
  1165.     if (table->parts[i].type != PART_SWAP) continue;
  1166.  
  1167.     for (j = 0; j < fstab.numEntries; j++) 
  1168.         if (!strcmp(table->parts[i].device, fstab.entries[j].device))
  1169.         break;
  1170.  
  1171.     if ((j < fstab.numEntries && fstab.entries[j].mntpoint) || 
  1172.         (firstTime && !testing))
  1173.         states[i] = '*';
  1174.     else
  1175.         states[i] = ' ';
  1176.  
  1177.     if (j < fstab.numEntries) 
  1178.         entries[i] = fstab.entries + j;
  1179.     else
  1180.         entries[i] = NULL;
  1181.  
  1182.     sprintf(buf, "/dev/%-5s  %9d  %9d  %9d", table->parts[i].device, 
  1183.         table->parts[i].begin, table->parts[i].end, 
  1184.         table->parts[i].size);
  1185.     check = newtCheckbox(2, 6 + top++, buf, states[i], NULL, 
  1186.                  &states[i]);
  1187.     newtFormAddComponent(checkList, check);
  1188.     }
  1189.  
  1190.     firstTime = 0;
  1191.  
  1192.     checkbox = newtCheckbox(2, 9, "Check for bad blocks during format",
  1193.                 chkBadBlocks ? '*' : ' ', NULL, &doCheck);
  1194.  
  1195.     okay = newtButton(9, 11, "Ok");
  1196.     cancel = newtButton(28, 11, "Cancel");
  1197.     
  1198.     newtFormAddComponents(form, text, label, checkList, checkbox, okay, 
  1199.               cancel, NULL);
  1200.  
  1201.     answer = newtRunForm(form);
  1202.  
  1203.     newtFormDestroy(form);
  1204.     newtPopWindow();
  1205.  
  1206.     chkBadBlocks = (doCheck != ' ');
  1207.  
  1208.     if (answer == cancel) {
  1209.     freeFstab(fstab);
  1210.     return INST_CANCEL;
  1211.     }
  1212.  
  1213.     for (i = 0; i < table->count; i++) {
  1214.     if (table->parts[i].type != PART_SWAP) continue;
  1215.  
  1216.         if (states[i] != ' ') {
  1217.         if (entries[i])
  1218.         entries[i]->mntpoint = strdup("swap");
  1219.         else {
  1220.         initFstabEntry(&entry);
  1221.         entry.device = strdup(table->parts[i].device);
  1222.         entry.size = table->parts[i].size;
  1223.         entry.type = table->parts[i].type;
  1224.         entry.tagName = table->parts[i].tagName;
  1225.         entry.mntpoint = strdup("swap");
  1226.  
  1227.         addFstabEntry(&fstab, entry);
  1228.         }
  1229.     } else if (entries[i]) {
  1230.         free(entries[i]->mntpoint);
  1231.         entries[i]->mntpoint = NULL;
  1232.     }
  1233.     }
  1234.  
  1235.     if (canEnableSwap) {
  1236.     for (i = 0; i < fstab.numEntries; i++) {
  1237.         if (fstab.entries[i].type == PART_SWAP &&
  1238.         fstab.entries[i].mntpoint) {
  1239.         enableswap(fstab.entries[i].device, 0, chkBadBlocks);
  1240.         canEnableSwap = 0;
  1241.         }
  1242.     }
  1243.     }
  1244.  
  1245.     freeFstab(*finalFstab);
  1246.     *finalFstab = copyFstab(&fstab);
  1247.     freeFstab(fstab);
  1248.  
  1249.     return 0;
  1250. }
  1251.